home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / 92052tar.gz / 920528.tar / ax25.c < prev    next >
C/C++ Source or Header  |  1992-05-14  |  11KB  |  424 lines

  1. /* @(#) $Header: ax25.c,v 1.13 92/05/14 13:19:43 deyke Exp $ */
  2.  
  3. /* Low level AX.25 code:
  4.  *  incoming frame processing (including digipeating)
  5.  *  IP encapsulation
  6.  *  digipeater routing
  7.  *
  8.  * Copyright 1991 Phil Karn, KA9Q
  9.  */
  10. #include <stdio.h>
  11. #include "global.h"
  12. #include "mbuf.h"
  13. #include "iface.h"
  14. #include "arp.h"
  15. #include "slip.h"
  16. #include "ax25.h"
  17. #include "lapb.h"
  18. #include "netrom.h"
  19. #include "ip.h"
  20. #include <ctype.h>
  21.  
  22. static int axsend __ARGS((struct iface *iface,char *dest,char *source,
  23.     int cmdrsp,int ctl,struct mbuf *data));
  24. static int axroute_hash __ARGS((char *call));
  25.  
  26. /* List of AX.25 multicast addresses in network format (shifted ascii).
  27.  * Only the first entry is used for transmission, but an incoming
  28.  * packet with any one of these destination addresses is recognized
  29.  * as a multicast.
  30.  */
  31. char Ax25multi[][AXALEN] = {
  32.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1, /* QST */
  33. /*      'M'<<1, 'A'<<1, 'I'<<1, 'L'<<1, ' '<<1, ' '<<1, '0'<<1, /* MAIL */
  34.     'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1, '0'<<1, /* NODES */
  35. /*      'I'<<1, 'D'<<1, ' '<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1, /* ID */
  36. /*      'O'<<1, 'P'<<1, 'E'<<1, 'N'<<1, ' '<<1, ' '<<1, '0'<<1, /* OPEN */
  37. /*      'C'<<1, 'Q'<<1, ' '<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1, /* CQ */
  38. /*      'B'<<1, 'E'<<1, 'A'<<1, 'C'<<1, 'O'<<1, 'N'<<1, '0'<<1, /* BEACON */
  39. /*      'R'<<1, 'M'<<1, 'N'<<1, 'C'<<1, ' '<<1, ' '<<1, '0'<<1, /* RMNC */
  40. /*      'A'<<1, 'L'<<1, 'L'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1, /* ALL */
  41.     '\0',
  42. };
  43. char Mycall[AXALEN];
  44. struct ax_route *Ax_routes[AXROUTESIZE];
  45. struct iface *axroute_default_ifp;
  46. int Digipeat = 2;       /* Controls digipeating */
  47.  
  48. /* Send IP datagrams across an AX.25 link */
  49. int
  50. ax_send(bp,iface,gateway,prec,del,tput,rel)
  51. struct mbuf *bp;
  52. struct iface *iface;
  53. int32 gateway;
  54. int prec;
  55. int del;
  56. int tput;
  57. int rel;
  58. {
  59.     char *hw_addr;
  60.  
  61.     if((hw_addr = res_arp(iface,ARP_AX25,gateway,bp)) == NULLCHAR)
  62.         return 0;       /* Wait for address resolution */
  63.  
  64.         /* Use UI frame */
  65.         return (*iface->output)(iface,hw_addr,iface->hwaddr,PID_IP,bp);
  66.  
  67. }
  68. /* Add header and send connectionless (UI) AX.25 packet.
  69.  * Note that the calling order here must match enet_output
  70.  * since ARP also uses it.
  71.  */
  72. int
  73. ax_output(iface,dest,source,pid,bp)
  74. struct iface *iface;    /* Interface to use; overrides routing table */
  75. char *dest;             /* Destination AX.25 address (7 bytes, shifted) */
  76. char *source;           /* Source AX.25 address (7 bytes, shifted) */
  77. int16 pid;              /* Protocol ID */
  78. struct mbuf *bp;        /* Data field (follows PID) */
  79. {
  80.     /* Prepend pid to data */
  81.     bp = pushdown(bp,1);
  82.     bp->data[0] = (char)pid;
  83.     return axsend(iface,dest,source,LAPB_COMMAND,UI,bp);
  84. }
  85. /* Common subroutine for sendframe() and ax_output() */
  86. static int
  87. axsend(iface,dest,source,cmdrsp,ctl,bp)
  88. struct iface *iface;    /* Interface to use; overrides routing table */
  89. char *dest;             /* Destination AX.25 address (7 bytes, shifted) */
  90. char *source;           /* Source AX.25 address (7 bytes, shifted) */
  91. int cmdrsp;             /* Command/response indication */
  92. int ctl;                /* Control field */
  93. struct mbuf *bp;        /* Data field (includes PID) */
  94. {
  95.     struct ax25 addr;
  96.     struct ax_route *dp,*rp;
  97.     int rval;
  98.     struct mbuf *data;
  99.     int i;
  100.  
  101.     /* If the source addr is unspecified, use the interface address */
  102.     if(source[0] == '\0')
  103.         source = iface->hwaddr;
  104.  
  105.     memcpy(addr.dest,dest,AXALEN);
  106.     memcpy(addr.source,source,AXALEN);
  107.     addr.cmdrsp = cmdrsp;
  108.  
  109.     addr.ndigis = 0;
  110.     /* If there's a digipeater route, get it */
  111.     if (rp = ax_routeptr(dest, 0)) {
  112.         for (dp = rp->digi; dp; dp = dp->digi)
  113.             addr.ndigis++;
  114.         i = addr.ndigis;
  115.         for (dp = rp->digi; dp; dp = dp->digi) {
  116.             i--;
  117.             if (i < MAXDIGIS)
  118.                 addrcp(addr.digis[i], dp->call);
  119.         }
  120.     }
  121.  
  122.     addr.nextdigi = 0;
  123.  
  124.     /* Allocate mbuf for control field, and fill in */
  125.     bp = pushdown(bp,1);
  126.     bp->data[0] = ctl;
  127.  
  128.     if((data = htonax25(&addr,bp)) == NULLBUF){
  129.         free_p(bp);
  130.         return -1;
  131.     }
  132.     /* This shouldn't be necessary because redirection has already been
  133.      * done at the IP router layer, but just to be safe...
  134.      */
  135.     if(iface->forw != NULLIF){
  136.         rval = (*iface->forw->raw)(iface->forw,data);
  137.     } else {
  138.         rval = (*iface->raw)(iface,data);
  139.     }
  140.     return rval;
  141. }
  142.  
  143. /* Process incoming AX.25 packets.
  144.  * After optional tracing, the address field is examined. If it is
  145.  * directed to us as a digipeater, repeat it.  If it is addressed to
  146.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  147.  */
  148. void
  149. ax_recv(iface,bp)
  150. struct iface *iface;
  151. struct mbuf *bp;
  152. {
  153.     struct mbuf *hbp;
  154.     char control;
  155.     struct ax25 hdr;
  156.     char (*mpp)[AXALEN];
  157.     int mcast;
  158.  
  159.     /* Pull header off packet and convert to host structure */
  160.     if(ntohax25(&hdr,&bp) < 0){
  161.         /* Something wrong with the header */
  162.         iface->ax25errors++;
  163.         free_p(bp);
  164.         return;
  165.     }
  166.     /* If there were digis in this packet, then the last digi was the
  167.      * actual transmitter. Otherwise the source is the transmitter.
  168.      */
  169.  
  170.     if(hdr.nextdigi < hdr.ndigis){
  171.         /* Packet hasn't passed all digipeaters yet. See if
  172.          * we have to repeat it.
  173.          */
  174.         if(Digipeat && addreq(hdr.digis[hdr.nextdigi],iface->hwaddr)){
  175.             /* Yes, kick it back out. htonax25 will set the
  176.              * repeated bit.
  177.              */
  178.             axroute_add(iface, &hdr, 0);
  179.             hdr.nextdigi++;
  180.             switch(Digipeat){
  181.             case 1:
  182.                 if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  183.                     axroute(NULL,hbp);
  184.                     bp = NULLBUF;
  185.                 }
  186.                 break;
  187.             case 2:
  188.                 lapb_input(iface,&hdr,bp);
  189.                 bp = NULLBUF;
  190.                 break;
  191.             }
  192.         }
  193.         free_p(bp);     /* Dispose if not forwarded */
  194.         return;
  195.     }
  196.     /* If we reach this point, then the packet has passed all digis,
  197.      * but it is not necessarily for us.
  198.      */
  199.     if(bp == NULLBUF){
  200.         /* Nothing left */
  201.         return;
  202.     }
  203.     /* Examine destination to see if it's either addressed to us or
  204.      * a multicast.
  205.      */
  206.     mcast = 0;
  207.     for(mpp = Ax25multi;(*mpp)[0];mpp++){
  208.         if(addreq(hdr.dest,*mpp)){
  209.             mcast = 1;
  210.             break;
  211.         }
  212.     }
  213.     if(!mcast && !addreq(hdr.dest,iface->hwaddr)){
  214.         /* Not a broadcast, and not addressed to us; ignore */
  215.         free_p(bp);
  216.         return;
  217.     }
  218.  
  219.     if(!mcast)
  220.         axroute_add(iface, &hdr, 0);
  221.  
  222.     /* Sneak a peek at the control field. This kludge is necessary because
  223.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  224.      * sublayers; a control value of UI indicates that LAPB is to be
  225.      * bypassed.
  226.      */
  227.     control = *bp->data & ~PF;
  228.  
  229.     if(uchar(control) == UI){
  230.         int pid;
  231.         struct axlink *ipp;
  232.  
  233.         (void) PULLCHAR(&bp);
  234.         if((pid = PULLCHAR(&bp)) == -1)
  235.             return;         /* No PID */
  236.         /* Find network level protocol and hand it off */
  237.         for(ipp = Axlink;ipp->funct        ;ipp++){
  238.             if(ipp->pid == pid)
  239.                 break;
  240.         }
  241.         if(ipp->funct        )
  242.             (*ipp->funct)(iface,(void *) 0,hdr.source,hdr.dest,bp,mcast);
  243.         else
  244.             free_p(bp);
  245.         return;
  246.     }
  247.     /* Everything from here down is connected-mode LAPB, so ignore
  248.      * multicasts
  249.      */
  250.     if(mcast){
  251.         free_p(bp);
  252.         return;
  253.     }
  254.  
  255.     lapb_input(iface,&hdr,bp);
  256. }
  257.  
  258. /*---------------------------------------------------------------------------*/
  259.  
  260. static int  axroute_hash(call)
  261. char  *call;
  262. {
  263.   long  hashval;
  264.  
  265.   hashval  = ((*call++ << 23) & 0x0f000000);
  266.   hashval |= ((*call++ << 19) & 0x00f00000);
  267.   hashval |= ((*call++ << 15) & 0x000f0000);
  268.   hashval |= ((*call++ << 11) & 0x0000f000);
  269.   hashval |= ((*call++ <<  7) & 0x00000f00);
  270.   hashval |= ((*call++ <<  3) & 0x000000f0);
  271.   hashval |= ((*call   >>  1) & 0x0000000f);
  272.   return hashval % AXROUTESIZE;
  273. }
  274.  
  275. /*---------------------------------------------------------------------------*/
  276.  
  277. struct ax_route *ax_routeptr(call, create)
  278. char  *call;
  279. int  create;
  280. {
  281.  
  282.   int  hashval;
  283.   struct ax_route *rp;
  284.  
  285.   hashval = axroute_hash(call);
  286.   for (rp = Ax_routes[hashval]; rp && !addreq(rp->call, call); rp = rp->next) ;
  287.   if (!rp && create) {
  288.     rp = (struct ax_route *) calloc(1, sizeof(struct ax_route ));
  289.     addrcp(rp->call, call);
  290.     rp->next = Ax_routes[hashval];
  291.     Ax_routes[hashval] = rp;
  292.   }
  293.   return rp;
  294. }
  295.  
  296. /*---------------------------------------------------------------------------*/
  297.  
  298. void axroute_add(iface, hdr, perm)
  299. struct iface *iface;
  300. struct ax25 *hdr;
  301. int  perm;
  302. {
  303.  
  304.   char (*mpp)[AXALEN];
  305.   char  *call;
  306.   char  *calls[MAXDIGIS+1];
  307.   int  i;
  308.   int  j;
  309.   int  ncalls = 0;
  310.   struct ax_route *lastnode = 0;
  311.   struct ax_route *rp;
  312.  
  313.   call = hdr->source;
  314.   if (!*call || addreq(call, iface->hwaddr)) return;
  315.   for (mpp = Ax25multi; (*mpp)[0]; mpp++)
  316.     if (addreq(call, *mpp)) return;
  317.   calls[ncalls++] = call;
  318.   for (i = 0; i < hdr->nextdigi; i++) {
  319.     call = hdr->digis[i];
  320.     if (!*call || addreq(call, iface->hwaddr)) return;
  321.     for (mpp = Ax25multi; (*mpp)[0]; mpp++)
  322.       if (addreq(call, *mpp)) return;
  323.     for (j = 0; j < ncalls; j++)
  324.       if (addreq(call, calls[j])) return;
  325.     calls[ncalls++] = call;
  326.   }
  327.  
  328.   for (i = ncalls - 1; i >= 0; i--) {
  329.     rp = ax_routeptr(calls[i], 1);
  330.     if (perm || !rp->perm) {
  331.       if (lastnode) {
  332.     rp->digi = lastnode;
  333.     rp->ifp = 0;
  334.       } else {
  335.     rp->digi = 0;
  336.     rp->ifp = iface;
  337.       }
  338.       rp->perm = perm;
  339.     }
  340.     rp->time = secclock();
  341.     lastnode = rp;
  342.   }
  343.   axroute_savefile();
  344. }
  345.  
  346. /*---------------------------------------------------------------------------*/
  347.  
  348. void axroute(cp, bp)
  349. struct ax25_cb *cp;
  350. struct mbuf *bp;
  351. {
  352.  
  353.   char  *dest;
  354.   struct ax_route *rp;
  355.   struct iface *ifp;
  356.  
  357.   if (cp && cp->ifp)
  358.     ifp = cp->ifp;
  359.   else {
  360.     if (bp->data[AXALEN + 6] & E)
  361.       dest = bp->data;
  362.     else
  363.       for (dest = bp->data + 2 * AXALEN; ; dest += AXALEN) {
  364.     if (!(dest[6] & REPEATED)) break;
  365.     if (dest[6] & E) {
  366.       dest = bp->data;
  367.       break;
  368.     }
  369.       }
  370.     rp = ax_routeptr(dest, 0);
  371.     ifp = (rp && rp->ifp) ? rp->ifp : axroute_default_ifp;
  372.   }
  373.   if (ifp) {
  374.     if (ifp->forw) ifp = ifp->forw;
  375.     (*ifp->raw)(ifp, bp);
  376.   } else
  377.     free_p(bp);
  378. }
  379.  
  380. /*---------------------------------------------------------------------------*/
  381.  
  382. /* Handle ordinary incoming data (no network protocol) */
  383. void
  384. axnl3(iface,axp,src,dest,bp,mcast)
  385. struct iface *iface;
  386. struct ax25_cb *axp;
  387. char *src;
  388. char *dest;
  389. struct mbuf *bp;
  390. int mcast;
  391. {
  392.     free_p(bp);
  393. }
  394.  
  395. /*---------------------------------------------------------------------------*/
  396.  
  397. char  *ax25hdr_to_string(hdr)
  398. struct ax25 *hdr;
  399. {
  400.  
  401.   char  *p;
  402.   int  i;
  403.   static char  buf[128];
  404.  
  405.   if (!*hdr->dest) return "*";
  406.   p = buf;
  407.   if (*hdr->source) {
  408.     pax25(p, hdr->source);
  409.     while (*p) p++;
  410.     *p++ = '-';
  411.     *p++ = '>';
  412.   }
  413.   pax25(p, hdr->dest);
  414.   while (*p) p++;
  415.   for (i = 0; i < hdr->ndigis; i++) {
  416.     *p++ = ',';
  417.     pax25(p, hdr->digis[i]);
  418.     while (*p) p++;
  419.     if (i < hdr->nextdigi) *p++ = '*';
  420.   }
  421.   *p = '\0';
  422.   return buf;
  423. }
  424.